package com.fzu.geometa.metadata.controller;

import cn.hutool.core.util.ObjectUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fzu.geometa.metadata.annotation.LoginRequired;
import com.fzu.geometa.metadata.model.po.Item;
import com.fzu.geometa.metadata.model.po.Register;
import com.fzu.geometa.metadata.model.vo.TreeNode;
import com.fzu.geometa.metadata.service.RegisterService;
import com.fzu.geometa.metadata.service.TreeNodeService;
import com.fzu.geometa.metadata.common.Status;
import com.fzu.geometa.metadata.service.ItemService;
import com.fzu.geometa.metadata.service.MetadataService;
import com.fzu.geometa.metadata.util.HostHolder;
import org.dom4j.DocumentException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;
import java.util.*;

import static com.fzu.geometa.common.model.dto.RestResponse.validFail;
import static com.fzu.geometa.metadata.util.XmlUtils.formatXml;

@Controller
public class UIController {
    @Autowired
    private MetadataService metadataService;
    @Autowired
    private ItemService itemService;
    @Autowired
    private TreeNodeService treeNodeService;

    @Autowired
    private RegisterService registerService;

    @Autowired
    private HostHolder hostHolder;

    private ObjectMapper objectMapper = new ObjectMapper();


    @GetMapping(path = "/listTreeNode/")
    @ResponseBody
    public Map<String, Object> listTreeNode(Long cid) {
        List<TreeNode> treeNodes = treeNodeService.listByCid(cid);
        Map<String, Object> map = new HashMap<>();
        map.put("status", new Status(200,"succeed"));
        map.put("data", treeNodes);
        return map;
    }

    @GetMapping(path = "/listTreeNodes/")
    @ResponseBody
    @LoginRequired
    public Map<String, Object> listTreeNode(String coverageId) {
        Register register = registerService.getByCoverageId(coverageId);

        if (ObjectUtil.isNull(register)) {
            return emptyData();
        }
        // 必须是属于该用户的数据
        if (register.getUserId() != null && register.getUserId().equals(
                hostHolder.getUser().getId())) {
            Map<String, Object> map = new HashMap<>();
            List<TreeNode> treeNodes = treeNodeService.listByCoverageId(coverageId);
            map.put("status", new Status(200,"succeed"));
            map.put("data", treeNodes);
            return map;
        } else {
            return emptyData();
        }
    }

    private Map<String, Object> emptyData() {
        Map<String, Object> map = new HashMap<>();
        map.put("status", new Status(500,"no data"));
        map.put("data", Collections.emptyList());
        return map;
    }

    @GetMapping(path = "/itemDetail/{eid}")
    public String getItemDetail(@PathVariable Long eid, Model model) {
        Item item = itemService.getById(eid);
        // 格式化 json
        if (item.getAttributes() != null) {
            try {
                JsonNode jsonNode = objectMapper.readTree((String) item.getAttributes());
                String formattedJson = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonNode);
                item.setAttributes(formattedJson);
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
        }
        model.addAttribute("item",item);
        return "itemDetail";
    }

    @GetMapping(path = "/viewDoc/{coverageId}")
    public String viewDoc(@PathVariable String coverageId, Model model) {
        String metaData = metadataService.getMetadata(coverageId);
        // 格式化文档
        try {
            metaData = formatXml(metaData);
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        model.addAttribute("xmlDoc",metaData);
        return "viewDoc";
    }

}
